from common.decorators import catch_error
from app.order.purchase import service
from app.user.decorators import token_required
from common.responses import ok
from flask_restplus import Resource, Namespace, fields, marshal, reqparse, Model

from common import constant
from flask import g
from common.request_parser import get_parser as base_get_parser
from app.order.purchase_return.model import PurchaseReturnOrder, PurchaseReturnOrderSku
from app.order.purchase_return import dao
from exts import db
from app.file.model import FileRelation, File
from app.file.controller import file_model
from datetime import datetime
from app.customer.controller import customer_model
from app.storage.warehouse.controller import warehouse_model
from app.finance.account.controller import account_model
from app.product.sku.controller import sku_model
from app.product.unit.controller import unit_model
from app.file.service import get_img_files_from_belong
from common.utils import get_default_date
from common import errors

api = Namespace('purchase_return_order')

# ---------- model ----------
purchase_return_order_sku_model = Model('purchase_return_order_sku_model', {
    'id': fields.Integer(description='编号'),
    "sku_id": fields.Integer(),
    'sku': fields.Nested(sku_model),
    'unit_id': fields.Integer(),
    'unit': fields.Nested(unit_model),
    "num": fields.Float(),
    "price": fields.Float(),
    "discount": fields.Float(),
    "notes": fields.String(),
})

purchase_return_order_model_for_list = Model('purchase_return_order_model_for_list', {
    'id': fields.Integer(description='编号'),
    'order_sn': fields.String(description='单据编号'),
    'status': fields.String(description='状态'),
    'draft_status': fields.String(description='草稿状态'),
    'date': fields.Date(description='日期'),

    'notes': fields.String(description='备注'),
    # 'is_active': fields.Boolean(description='启用状态'),
    "create_datetime": fields.DateTime(description='创建时间'),
    "update_datetime": fields.DateTime(description='更新时间'),

    "customer_id": fields.Integer(),
    "warehouse_id": fields.Integer(),
    "account_id": fields.Integer(),
    'customer': fields.Nested(customer_model),
    "account": fields.Nested(account_model),
    "warehouse": fields.Nested(warehouse_model),

    # "second_account_id": fields.Integer(),
    "tracking_number": fields.String(),
    "is_make": fields.Boolean(),
    "bill_info": fields.String(),
    'reduce_price': fields.Float(),

    "income": fields.Float(),
})

purchase_return_order_model_for_detail = purchase_return_order_model_for_list.inherit('purchase_return_order_model_for_detail', {
    "order_skus": fields.Nested(purchase_return_order_sku_model),
    # 图片
    'images': fields.List(fields.Nested(file_model),
                          attribute=lambda purchase_return_order: get_img_files_from_belong(
                              purchase_return_order.id, constant.FileBelongType.PURCHASE_ORDER)),
})

# ---------- create parser ----------  用组装的方式，不用继承
create_parser = reqparse.RequestParser()
create_parser.add_argument('date', type=str, help='单据日期')
create_parser.add_argument('draft_status', type=str, help='草稿状态', default=constant.OrderDraftStatus.PENDING)
create_parser.add_argument('customer_id', type=str, help='供应商')
create_parser.add_argument('warehouse_id', type=str, help='仓库')
create_parser.add_argument('account_id', type=str, help='结算账户')
create_parser.add_argument('tracking_number', type=str, help='快递单号')
create_parser.add_argument('is_make', type=str, help='是否开票')
create_parser.add_argument('bill_info', type=str, help='开票信息')
create_parser.add_argument('reduce_price', type=float, help='抹零金额')
create_parser.add_argument('notes', type=str, help='备注')
create_parser.add_argument('order_skus', action='append', type=dict, help='商品明细')
create_parser.add_argument('image_ids', type=int, help='图片id', action='append', default=[])
create_parser.add_argument('action', type=str, required=True, help='操作',
                           choices=[constant.OrderActionType.SAVE_DRAFT,
                                    constant.OrderActionType.SUBMIT])
# ---------- get parser ----------
get_parser = base_get_parser.copy()  # 状态，日期开始+结束，供应商，单号及搜索框
get_parser.add_argument('status', type=str, help='状态',
                        choices=[constant.OrderStatus.DRAFT,
                                 constant.OrderStatus.SUCCESS,
                                 constant.OrderStatus.REVOKE])
get_parser.add_argument('draft_status', type=str, help='草稿状态',
                        choices=[constant.OrderDraftStatus.PENDING])
get_parser.add_argument('customer_id', type=int, help='供应商id')
get_parser.add_argument('warehouse_id', type=int, help='仓库id')
get_parser.add_argument('date_begin', type=str, help='开始日期')
get_parser.add_argument('date_end', type=str, help='结束日期')

# ---------- put parser ----------
put_parser = create_parser.copy()


class PurchaseReturnOrdersResource(Resource):
    @catch_error
    @token_required
    @api.expect(create_parser)
    def post(self):
        """创建"""
        args = create_parser.parse_args()
        order_skus = args.pop('order_skus')
        image_ids = args.pop('image_ids')
        action = args.pop('action')
        args['date'] = get_default_date(args.pop('date'))

        # 创建order
        new_purchase_return_order = PurchaseReturnOrder.create(
            **args,
            order_sn=PurchaseReturnOrder.generate_order_sn_purchase(),
            commit=True
        )
        # 创建order_sku
        for order_sku_json in order_skus:
            PurchaseReturnOrderSku.create(
                order_id=new_purchase_return_order.id,
                **order_sku_json,
            )
        # images
        if image_ids or len(image_ids) == 0:
            for image_id in image_ids:
                FileRelation.create(
                    file_id=image_id, belong_id=new_purchase_return_order.id,
                    belong_type=constant.FileBelongType.PURCHASE_ORDER)

        if action == constant.OrderActionType.SUBMIT:
            new_purchase_return_order.submit()

        db.session.commit()
        return ok(data=marshal(new_purchase_return_order, purchase_return_order_model_for_detail),
                  message='create success')

    @catch_error
    @token_required
    @api.expect(get_parser)
    def get(self):
        """获取列表"""
        args = get_parser.parse_args()
        pagination = dao.get_by_page(**args)
        # 重新获取
        new_items = []
        for ele in pagination['items']:
            purchase_return_order = PurchaseReturnOrder.query.filter_by(id=ele['id']).first()
            new_items.append(marshal(purchase_return_order, purchase_return_order_model_for_list))
        pagination['items'] = new_items

        return ok(data=pagination,
                  message='get success')


class PurchaseReturnOrderResource(Resource):
    @catch_error
    @token_required
    def get(self, obj_id):
        """获取"""
        obj = PurchaseReturnOrder.query.filter_by(id=obj_id).first()
        return ok(data=marshal(obj, purchase_return_order_model_for_detail),
                  message='get success')

    @catch_error
    @token_required
    @api.expect(put_parser)
    def put(self, obj_id):
        """更新 保存或提交"""
        args = put_parser.parse_args()
        action = args.pop('action')
        order_skus = args.pop('order_skus')
        obj = PurchaseReturnOrder.query.filter_by(id=obj_id).first()

        if action == constant.OrderActionType.SAVE_DRAFT:
            obj.save_draft(order_skus, **args)
        elif action == constant.OrderActionType.SUBMIT:
            obj.save_draft(order_skus, **args)
            obj.submit()
        else:
            raise errors.BadRequestError('错误的操作类型')
        return ok(data=marshal(obj, purchase_return_order_model_for_detail),
                  message='update success')

    @catch_error
    @token_required
    def delete(self, obj_id):
        """删除"""
        obj = PurchaseReturnOrder.query.filter_by(id=obj_id).first()
        # 检查状态
        if obj.status != constant.OrderStatus.DRAFT:
            raise errors.BadRequestError('只有草稿状态才能删除')
        delete_id = obj.hard_delete(commit=True)
        return ok(
            data={
                'id': delete_id
            },
            message='delete success')


action_parser = reqparse.RequestParser()
action_parser.add_argument('action', type=str, required=True, help='操作',
                           choices=[constant.OrderActionType.REVOKE])


class PurchaseReturnOrderActionResource(Resource):
    @catch_error
    @token_required
    def put(self, obj_id):
        """撤销"""
        args = action_parser.parse_args()
        obj = PurchaseReturnOrder.query.filter_by(id=obj_id).first()
        action = args.pop('action')
        if action == constant.OrderActionType.REVOKE:
            obj.revoke()
            return ok(data=marshal(obj, purchase_return_order_model_for_detail),
                      message='update success')
        else:
            raise Exception("wrong action")


# --------- route ----------
api.add_resource(PurchaseReturnOrdersResource, '/purchase_return_orders')
api.add_resource(PurchaseReturnOrderResource, '/purchase_return_orders/<int:obj_id>')
api.add_resource(PurchaseReturnOrderActionResource, '/purchase_return_orders/<int:obj_id>/action')  # 撤销

# 注册 response 文档
api.models[purchase_return_order_model_for_detail.name] = purchase_return_order_model_for_detail
